package tasks

import (
	"errors"
	"fmt"
	"strings"

	"torler.com/qingyue/apps/spider/internal/core"
	"torler.com/qingyue/apps/spider/internal/core/task"
	"torler.com/qingyue/common/database"
	"torler.com/qingyue/common/model"
	"torler.com/qingyue/common/types"
)

const (
	RUNNER_INSTORE_BOOK = types.RunnerName("spider_instore_book")
	TASK_INSTORE_BOOK   = types.TaskName("小说入库")
)

// BookInstoreTask 小说小说入库
//
// 根据小说名和作者名在小库中创建小说
type BookInstoreTask struct {
}

func NewBookInstoreTask() *BookInstoreTask {
	return &BookInstoreTask{}
}

// 任务执行者预加载
func (it *BookInstoreTask) Preload(t *task.Task) error {
	return nil
}

// 任务执行者的唯一名称标识用于反序列化
func (it *BookInstoreTask) Name() types.RunnerName {
	return RUNNER_INSTORE_BOOK
}

// 任务执行者
func (it *BookInstoreTask) Run(tsk *task.Task) error {
	ctx := tsk.GetCtx()
	err1 := it.saveNewCBookFromLastest(ctx, tsk)
	err2 := it.saveNewBookFromCBook(ctx, tsk)

	// 以下为小说的入库到上架的操作
	//0>1  新书入库
	err3 := it.syncBookInfoFromCBook(ctx, tsk)
	//1>2  从本地获取章节内容
	err4 := it.featchChapterContentFromLocal(ctx, tsk)
	//2->3 从渠道获取章节内容
	err5 := it.featchChapterContentFromChannel(tsk)
	//3>4 整理小说
	err6 := it.syncProcessBookAndChapter(tsk)
	// 4>5 上架
	//4>-1 未满足上架条件
	err7 := it.checkBookCanShelfOrNot(tsk)
	return errors.Join(err1, err2, err3, err4, err5, err6, err7)

}

// 从最近更新列表中获取新的小说，并保存到渠道小说表中
func (it *BookInstoreTask) saveNewCBookFromLastest(ctx *core.AppContext, tsk *task.Task) error {
	db := ctx.DB
	sql := "SELECT t1.* FROM sp_raw_book_lastest AS t1  LEFT JOIN sp_raw_book AS t2 ON t1.oid=t2.oid AND t1.site_id=t2.site_id WHERE t2.id IS NULL"
	var lasts []*model.LastestCBook
	var cbooks []*model.RawBook
	tx := db.Raw(sql).Scan(&lasts)
	if tx.Error != nil {
		return tx.Error
	}
	count := len(lasts)
	if count > 0 {
		for _, book := range lasts {
			var cbook = model.NewRawBook(book.SiteId, book.OId)
			cbook.BookName = book.BookName
			cbook.Author = book.Author
			cbook.SourceId = book.SiteId
			cbooks = append(cbooks, cbook)
		}
		tx := database.BatchSave(db, cbooks)
		if tx.Error != nil {
			return tx.Error
		}
		count = int(tx.RowsAffected)

	}

	tsk.SetResult("渠道表新增小说数量", count)
	return nil
}

// 从渠道小说中获取新的小说保存到正式小说表中,并建立匹配关系
func (it *BookInstoreTask) saveNewBookFromCBook(ctx *core.AppContext, tsk *task.Task) error {
	db := ctx.DB
	//从渠道中根据书名和作者在小说库中创建新的小说
	sql := `SELECT
				t1.book_name,
				t1.author 
			FROM
				sp_raw_book AS t1
				LEFT JOIN sp_book AS t2 ON t1.book_name = t2.book_name 
				AND t1.author = t2.author 
			WHERE
				t1.book_id = 0 
			GROUP BY
				t1.book_name,
				t1.author;`
	var books []*model.BookInfo
	tx := db.Raw(sql).Scan(&books)
	if tx.Error != nil {
		return tx.Error
	}
	count := len(books)
	if count > 0 {
		tx := database.BatchSave(db, books)
		if tx.Error != nil {
			return tx.Error
		}
		count = int(tx.RowsAffected)
	}
	tsk.SetResult("正式小说表新增数量", count)

	//渠道小说和小说正式表中的小说建立关系：
	sql = `UPDATE sp_raw_book AS t1
				JOIN sp_book AS t2 
					ON t1.book_name = t2.book_name 
					AND t1.author = t2.author
				SET t1.book_id = t2.id
				WHERE t1.book_id = 0;`
	tx = db.Exec(sql)
	if tx.Error != nil {
		return errors.New("匹配小说关系失败")

	}
	count = int(tx.RowsAffected)
	tsk.SetResult("渠道小说匹配正式小说数量", count)
	return nil
}

// 同步渠道小说信息
//
//	小说的状态：0->1
func (it *BookInstoreTask) syncBookInfoFromCBook(ctx *core.AppContext, tsk *task.Task) error {
	db := ctx.DB
	sql := `
		UPDATE sp_book AS b
		INNER JOIN (
			SELECT
				cb.book_id,
				cb.img_url,
				cb.DESC,
				cb.category_name,
				cb.write_state,
				cb.chapter_count 
			FROM
				sp_raw_book AS cb
				INNER JOIN ( SELECT book_id, MAX( score ) AS max_score FROM sp_raw_book GROUP BY book_id ) AS highest_score ON cb.book_id = highest_score.book_id 
				AND cb.score = highest_score.max_score 
			) AS cb ON b.id = cb.book_id 
			SET b.img_url = cb.img_url,
			b.DESC = cb.DESC,
			b.category_name = cb.category_name,
			b.write_state = cb.write_state,
			b.chapter_count = cb.chapter_count,
			b.state = ?
		WHERE
			b.state = ?`
	tx := db.Exec(sql, types.BookStateInfoFetched, types.BookStateDefault)
	count := tx.RowsAffected
	tsk.SetResult("从渠道同步小说基本信息数量", count)

	return nil

}

// 发布从本地书源中获取章节内容的任务 1>2
func (it *BookInstoreTask) featchChapterContentFromLocal(ctx *core.AppContext, tsk *task.Task) error {
	var books []*model.BookInfo
	db := ctx.DB

	db.Where(&model.BookInfo{State: types.BookStateInfoFetched}).Find(&books)
	count := len(books)
	tsk.SetResult("尝试从本地获取导入的小说数量", count)

	//模糊匹配 查询lbookinfo中file_name包含book.BookName的所有lbookinfo
	for _, book := range books {
		var lbooks []*model.RawBook
		db.Where(`
				MATCH(file_name) AGAINST(? IN BOOLEAN MODE)
				AND meta_state = ?
				AND delat IS NULL`, "+"+strings.ReplaceAll(book.BookName, " ", " +"), types.MetaStateDefault).Find(&lbooks)

		for _, lbook := range lbooks {
			name := fmt.Sprintf("%s.%s", TASK_LOCAL_BOOK_PROCESS, lbook.Id)
			t := task.NewTask(ctx, types.TaskName(name), RUNNER_LOCAL_BOOK_PROCESS, task.WithParam("book_id", book.Id), task.WithRunModeOnce(), task.WithParam("lbook_id", lbook.Id))
			tsk.TaskManager().AddTask(t)
		}

	}
	tsk.SetResult("需要处理的本地小说数量", count)

	return nil
}

// 发布从渠道中获取章节内容的任务

func (it *BookInstoreTask) featchChapterContentFromChannel(tsk *task.Task) error {
	return nil
}

// 同步处理书籍和章节信息
func (it *BookInstoreTask) syncProcessBookAndChapter(tsk *task.Task) error {
	return nil
}

// 检测书籍是否可以上架
func (it *BookInstoreTask) checkBookCanShelfOrNot(tsk *task.Task) error {
	return nil
}
